/*------------------------------------------------------------------------------
 * Copyright 2012 NCR Corporation
 *------------------------------------------------------------------------------
 * All revision information is updated automatically from source code control
 * change records - please do not manually edit.
 *------------------------------------------------------------------------------
 *
 * $LastChangedRevision:: 2031                                     $
 * $LastChangedBy:: rb250096                                       $
 * $LastChangedDate:: 2012-04-08 18:21:06 -0400 (Sun, 08 Apr 2012) $
 */

package com.ncr.nep.dashboardcore.ui.client;

import java.util.Map;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.UIObject;

/**
 * Widget that displays a single-level popup menu.  To use, a map of
 * strings representing unique menu item IDs mapped to displayed labels is
 * provided to the constructor.
 *
 * @author rb250096
 * @version $Revision: 2031 $
 */
public class PopupMenu extends PopupPanel implements
        ClickHandler, HasPopupMenuHandlers {

    //--------------------------------------------------------------------------
    //
    //  Inner classes
    //
    //--------------------------------------------------------------------------

    /**
     * HTML templates for generating the popup menu items.
     */
    interface Templates extends SafeHtmlTemplates {

        @Template("<i class='arrow'></i><ul>{0}</ul>")
        SafeHtml menu(SafeHtml menuContents);

        @Template("<li data:id='{0}'>{1}</li>")
        SafeHtml menuItem(String menuId, String label);

        @Template("<li class='divider'/>")
        SafeHtml divider();
    }

    //--------------------------------------------------------------------------
    //
    //  Fields
    //
    //--------------------------------------------------------------------------

    /**
     * Constant defining menu item ID of a divider.  This is used to add
     * divider elements to the list when setting the menu items in the
     * constructor.
     */
    public static final String DIVIDER = "divider";

    /**
     * HTML templates used to generate the menu items.
     */
    private static Templates templates = GWT.create(Templates.class);

    /**
     * Map of menu item IDs to menu item labels displayed in the generated
     * HTML.
     */
    protected Map<String, String> menuItems;

    /**
     * Widget containing generated HTML defining widget layout.
     */
    protected HTML layout;

    //--------------------------------------------------------------------------
    //
    //  Constructors
    //
    //--------------------------------------------------------------------------

    /**
     * Constructor
     *
     * @param menuItems Map of menu item IDs to menu item labels.  This map is
     *                  used to generate the contents of the menu.
     */
    public PopupMenu(Map<String, String> menuItems) {
        super(true);

        this.menuItems = menuItems;

        SafeHtmlBuilder builder = new SafeHtmlBuilder();
        for(String menuItemId : menuItems.keySet()) {
            if(menuItemId == DIVIDER) {
                builder.append(templates.divider());
            }
            else {
                builder.append(templates.menuItem(menuItemId,
                        menuItems.get(menuItemId)));
            }
        }

        this.layout = new HTML(templates.menu(builder.toSafeHtml()));
        this.layout.setStyleName("ds-PopupMenu");
        this.layout.addClickHandler(this);

        super.setWidget(this.layout);
    }

    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------

    /**
     * Sets the width of the popup menu.
     *
     * @param width The width of the popup.  This can be any valid CSS width
     *              string.
     */
    public void setPopupWidth(String width) {
        this.layout.setWidth(width);
    }

    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

    /**
     * Shows the popup menu relative to the specified widget.
     *
     * @param widget The widget to display the popup menu relative to.
     * @param useWidgetWidth If true, when displayed the popup menu's width
     *                       will be set to the same width as the widget it
     *                       is being displayed relative to (for when you want
     *                       the menu to be the same width visually).
     */
    public void showRelativeTo(UIObject widget, boolean useWidgetWidth) {
        if(useWidgetWidth) {
            int widgetWidth = widget.getOffsetWidth();
            this.layout.setWidth(String.valueOf(widgetWidth) + "px");
        }

        this.showRelativeTo(widget);
    }

    @Override
    public HandlerRegistration addPopupMenuHandler(PopupMenuHandler handler) {
        return this.addHandler(handler, PopupMenuEvent.TYPE);
    }

    //--------------------------------------------------------------------------
    //
    //  Event handlers
    //
    //--------------------------------------------------------------------------

    @Override
    public void onClick(ClickEvent event) {
        Element target = Element.as(event.getNativeEvent().getEventTarget());
        String targetClassName = target.getClassName();
        if(targetClassName != null && targetClassName.equals("divider")) {
            return;
        }

        String menuItemId = target.getAttribute("data:id");
        String menuItemLabel = target.getInnerHTML();

        if(menuItemId == null || menuItemId.length() == 0) {
            return;
        }

        this.hide();
        this.fireEvent(new PopupMenuEvent(menuItemId, menuItemLabel));
    }
}
